package com.fowo.api.sys.cns.impl;

import com.fowo.api.sys.cns.ChangeNoticeData;
import com.fowo.api.sys.cns.ChangeNoticeListener;
import com.fowo.api.sys.cns.ChangeNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 变更通知服务实现
 * @author yl_ls
 */
@Slf4j
@Service
public class ChangeNoticeServiceImpl implements ChangeNoticeService {
    @Resource
    private Collection<ChangeNoticeListener> listeners;

    @Override
    public void noticeBatchUpdate(String objectName) {
        ChangeNoticeData noticeData = new ChangeNoticeData();
        noticeData.setObjectName(objectName);
        noticeData.setType(ChangeNoticeData.TYPE_BATCH_ALL);
        notice(noticeData);
    }

    @Override
    public void noticeBatchUpdate(String objectName, Iterable<Long> insertKeys, Iterable<Long> updateKeys, Iterable<Long> removeKeys) {
        ChangeNoticeData noticeData = new ChangeNoticeData();
        noticeData.setObjectName(objectName);
        noticeData.setType(ChangeNoticeData.TYPE_BATCH);
        noticeData.setInsertKeys(toList(insertKeys));
        noticeData.setUpdateKeys(toList(updateKeys));
        noticeData.setRemoveKeys(toList(removeKeys));
        notice(noticeData);
    }

    @Override
    public void noticeInserts(String objectName, Iterable<Long> insertKeys) {
        ChangeNoticeData noticeData = new ChangeNoticeData();
        noticeData.setObjectName(objectName);
        noticeData.setType(ChangeNoticeData.TYPE_INSERT);
        noticeData.setInsertKeys(toList(insertKeys));
        notice(noticeData);
    }

    @Override
    public void noticeUpdates(String objectName, Iterable<Long> updateKeys) {
        ChangeNoticeData noticeData = new ChangeNoticeData();
        noticeData.setObjectName(objectName);
        noticeData.setType(ChangeNoticeData.TYPE_UPDATE);
        noticeData.setUpdateKeys(toList(updateKeys));
        notice(noticeData);
    }

    @Override
    public void noticeRemoves(String objectName, Iterable<Long> removeKeys) {
        ChangeNoticeData noticeData = new ChangeNoticeData();
        noticeData.setObjectName(objectName);
        noticeData.setType(ChangeNoticeData.TYPE_BATCH);
        noticeData.setRemoveKeys(toList(removeKeys));
        notice(noticeData);
    }

    private void notice(ChangeNoticeData noticeData) {
        for (ChangeNoticeListener listener : listeners) {
            try {
                listener.notice(noticeData);
            } catch (Exception e) {
                log.error("变更通知发送给 {} 时发生错误", listener, e);
            }
        }
    }

    private List<Long> toList(Iterable<Long> iterable) {
        List<Long> list = new ArrayList<>();
        iterable.forEach(list::add);
        return list;
    }
}
